<?php

class Captcha extends \Phalcon\Mvc\User\Plugin
{
    const PNGCODE = 0;
    const JPEGCODE = 1;
    const GIFCODE = 2;
    const MATHCODE = 3;

    const JIA = 0;
    const JIAN = 1;
    const CHENG = 2;
    const CHU = 3;

    public static $lastError;

    /**
     * 默认验证码源
     * @var string
     */
    public $chars = 'abcdefghijklmnopqrstuvwxyz123456789';

    /**
     * @var string 生成的验证码
     */
    public $code;

    /**
     * 验证码的位数
     * @var int
     */
    public $codeLength;

    public $codeLengthRange = [4,5,6];

    /**
     * 生存验证码图片的宽度
     * @var int
     */
    public $captchaWidth = 160;

    /**
     * 生存验证码图片的高度
     * @var int
     */
    public $captchaHeight = 40;

    /**
     * 验证码图片资源
     * @var resource
     */
    public $img;

    /**
     * 验证码的字体
     * @var string
     */
    public $font='C:/Windows/Fonts/ELEPHNTI.TTF';

    /**
     * 验证码字体大小
     * @var int
     */
    public $fontSize = 20;

    /**
     * 验证码的字体色
     * @var
     */
    public $fontColor;

//    public $numbers = [
//        0 => ['0', '零'],
//        1 => ['1', '一', '壹'],
//        2 => ['2', '二', '贰'],
//        3 => ['3', '三', '叁', '叄', '弎'],
//        4 => ['4', '四', '肆', '亖'],
//        5 => ['5', '五', '伍'],
//        6 => ['6', '六', '陆'],
//        7 => ['7', '七', '柒'],
//        8 => ['8', '八', '捌'],
//        9 => ['9', '九', '玖'],
//        10 => ['10', '十', '拾'],
//    ];
    public $numbers = [
        0 => ['0',],
        1 => ['1',],
        2 => ['2',],
        3 => ['3',],
        4 => ['4',],
        5 => ['5',],
        6 => ['6',],
        7 => ['7',],
        8 => ['8',],
        9 => ['9',],
        10 => ['10',],
    ];
//
//    public $operators = [
//        self::JIA => ['+', '加'],
//        self::JIAN => ['-', '减'],
//        self::CHENG => ['X', '乘'],
//        self::CHU => ['÷', '除以'],
//    ];

    public $operators = [
        self::JIA => ['+',],
        self::JIAN => ['-',],
        self::CHENG => ['X',],
        self::CHU => ['/', ],
    ];

    public function check($code)
    {
        return $code == $this->session->get('captcha');
    }

    public function __construct()
    {
        $this->font = __DIR__ . DIRECTORY_SEPARATOR . 'hwkt.ttf';
    }

    /**
     *生存验证码的验证码
     */
    public function createCode()
    {
        $charsLength = strlen($this->chars);
        $maxCharsIndex = $charsLength - 1;
        $this->codeLength = $this->codeLengthRange[array_rand($this->codeLengthRange, 1)];
        for ($i = 0; $i < $this->codeLength; $i++) {
            $this->code .= $this->chars[mt_rand(0, $maxCharsIndex)];
        }
        $this->session->set('captcha', $this->code);
    }

    /**
     * 创建图片资源
     */
    public  function createBg()
    {
        $this->img = imagecreatetruecolor($this->captchaWidth, $this->captchaHeight);
        $color = imagecolorallocate($this->img, mt_rand(230, 255), mt_rand(230, 255), mt_rand(230, 255));
        imagefilledrectangle($this->img, 0, $this->captchaHeight, $this->captchaWidth, 0, $color);
    }


    /**
     * 对验证码图片中的验证码应用字体
     */
    public  function createFont()
    {
        $_x = $this->captchaWidth / $this->codeLength;
        if (!is_file($this->font)) {
            throw new \Exception('字体文件不存在:' . $this->font);
        }
        for ($i = 0; $i < $this->codeLength; $i++) {
            $this->fontColor = imagecolorallocate($this->img, mt_rand(0, 30), mt_rand(0, 30), mt_rand(0, 30));
            imagettftext($this->img, $this->fontSize, mt_rand(-30, 30), $_x * $i + mt_rand(1, 5), $this->captchaHeight / 1.4, $this->fontColor, $this->font, $this->code[$i]);
        }
    }

    /**
     * 对验证码图片添加干扰线
     */
    public  function createLine()
    {
        for ($i = 0; $i < 6; $i++) {
            $color = imagecolorallocate($this->img, mt_rand(0, 40), mt_rand(0, 40), mt_rand(0, 40));
            imageline($this->img, mt_rand(0, $this->captchaWidth), mt_rand(0, $this->captchaHeight), mt_rand(0, $this->captchaWidth), mt_rand(0, $this->captchaHeight), $color);
        }
        for ($i = 0; $i < 100; $i++) {
            $color = imagecolorallocate($this->img, mt_rand(200, 255), mt_rand(200, 255), mt_rand(200, 255));
            imagestring($this->img, mt_rand(1, 5), mt_rand(0, $this->captchaWidth), mt_rand(0, $this->captchaHeight), '*', $color);
        }
    }

    public function genImgSource($code = null)
    {
        if ($code== null) {
            $this->createCode();
        } else {
            $this->code = $code;
            $this->codeLength = strlen($this->code);
        }
        $this->createBg();
//        $this->createLine();
        $this->createFont();
    }

    public function genPngCode($fileName = null)
    {
        $this->genImgSource();
        if ($fileName) {
            imagepng($this->img, $fileName);
            imagedestroy($this->img);
        } else {
            header("Pragma:no-cache");
            header("Cache-control:no-cache");
            header('Content-type:image/png');
            imagepng($this->img);
            imagedestroy($this->img);
        }
    }

    public function genJpegCode($fileName = null)
    {
        $this->genImgSource();
        if ($fileName) {
            imagejpeg($this->img, $fileName);
            imagedestroy($this->img);
        } else {
            header("Pragma:no-cache");
            header("Cache-control:no-cache");
            header('Content-type:image/png');
            imagejpeg($this->img);
            imagedestroy($this->img);
        }
    }

    public function genGifCode($fileName = null)
    {
        $this->createCode();
        $imageData=array();
        for($i = 0; $i < 5; $i++)
        {
            ob_start();
            $this->createBg();
//            $this->createLine();
            $this->createFont();
            imagegif($this->img);
            imagedestroy($this->img);
            $imageData[] = ob_get_contents();
            ob_clean();
            // ++$i;
        }
        $gif = new GIFEncoder($imageData);
        if ($fileName) {
            file_put_contents($fileName, $gif);
        } else {
            header("Pragma:no-cache");
            header("Cache-control:no-cache");
            header('Content-type:image/gif');
            echo $gif->GetAnimation();
        }
    }

    public function genMathCode($type = null, $fileName = null)
    {
        if ($type === null) {
            $type = array_rand($this->operators);
        }
        global $application;
        switch ($type) {
            case self::JIA:
                return $this->jiaCode();
            case self::JIAN:
                return $this->jianCode();
            case self::CHENG:
                return $this->chengCode();
            case self::CHU:
                return $this->chuCode();
            default:
                self::$lastError = '不支持的操作运算:'.$type;
                $application->logger->error(self::$lastError);
                return false;
        }
    }

    protected function jiaCode()
    {
        $firstNumber = array_rand($this->numbers, 1);
        $secondNumber = array_rand($this->numbers, 1);
        //第一个用于显示的数次
        $firstShows = $this->numbers[$firstNumber];
        $firstShow = $firstShows[array_rand($firstShows, 1)];
        //第二个用于显示的数字
        $secondShows = $this->numbers[$secondNumber];
        $secondShow = $secondShows[array_rand($secondShows, 1)];
        $jiaShows = $this->operators[self::JIA];
        $jiaShow = $jiaShows[array_rand($jiaShows, 1)];
        $result = $firstNumber + intval($secondNumber);
        $this->session->set('captcha', $result);
        $show = $firstShow.$jiaShow.$secondShow.'=?';
        $this->genImgSource($show);
        header("Pragma:no-cache");
        header("Cache-control:no-cache");
        header('Content-type:image/png');
        imagepng($this->img);
        imagedestroy($this->img);
        return true;
    }

    public function jianCode()
    {
        $firstNumber = array_rand($this->numbers, 1);
        $secondNumber = array_rand($this->numbers, 1);
        while ($firstNumber < $secondNumber) {
//            $secondNumber = array_rand($this->numbers, 1);
            $secondNumber = 1;
        }
        //第一个用于显示的数次
        $firstShows = $this->numbers[$firstNumber];
        $firstShow = $firstShows[array_rand($firstShows, 1)];
        //第二个用于显示的数字
        $secondShows = $this->numbers[$secondNumber];
        $secondShow = $secondShows[array_rand($secondShows, 1)];
        $jiaShows = $this->operators[self::JIAN];
        $jiaShow = $jiaShows[array_rand($jiaShows, 1)];
        $result = $firstNumber - intval($secondNumber);
        $this->session->set('captcha', $result);
        $show = $firstShow.$jiaShow.$secondShow.'=?';
        $this->genImgSource($show);
        header("Pragma:no-cache");
        header("Cache-control:no-cache");
        header('Content-type:image/png');
        imagepng($this->img);
        imagedestroy($this->img);
        return true;
    }

    public function chengCode()
    {
        $firstNumber = array_rand($this->numbers, 1);
        $secondNumber = array_rand($this->numbers, 1);
        //第一个用于显示的数次
        $firstShows = $this->numbers[$firstNumber];
        $firstShow = $firstShows[array_rand($firstShows, 1)];
        //第二个用于显示的数字
        $secondShows = $this->numbers[$secondNumber];
        $secondShow = $secondShows[array_rand($secondShows, 1)];
        $jiaShows = $this->operators[self::CHENG];
        $jiaShow = $jiaShows[array_rand($jiaShows, 1)];
        $result = $firstNumber * intval($secondNumber);
        $this->session->set('captcha', $result);
        $show = $firstShow.$jiaShow.$secondShow.'=?';
        $this->genImgSource($show);
        header("Pragma:no-cache");
        header("Cache-control:no-cache");
        header('Content-type:image/png');
        imagepng($this->img);
        imagedestroy($this->img);
        return true;
    }

    public function chuCode()
    {
        $firstNumber = array_rand($this->numbers, 1);
        $secondNumber = 0;
        $mod = 1;
        while ($secondNumber==0 || $mod!=0) {
//            $secondNumber = array_rand($this->numbers, 1);
            $secondNumber = 1;
            $mod = $firstNumber % $secondNumber;
        }
        //第一个用于显示的数次
        $firstShows = $this->numbers[$firstNumber];
        $firstShow = $firstShows[array_rand($firstShows, 1)];
        //第二个用于显示的数字
        $secondShows = $this->numbers[$secondNumber];
        $secondShow = $secondShows[array_rand($secondShows, 1)];
        $jiaShows = $this->operators[self::CHU];
        $jiaShow = $jiaShows[array_rand($jiaShows, 1)];
        $result = $firstNumber / intval($secondNumber);
        $this->session->set('captcha', $result);
        $show = $firstShow.$jiaShow.$secondShow.'=?';
        $this->genImgSource($show);
        header("Pragma:no-cache");
        header("Cache-control:no-cache");
        header('Content-type:image/png');
        imagepng($this->img);
        imagedestroy($this->img);
        return true;
    }

    public function genCaptcha($type= null, $fileName = null)
    {
        global $application;
        if ($type === null) {
            $types = [self::GIFCODE, self::PNGCODE, self::JPEGCODE, self::MATHCODE];
            $type = $types[array_rand($types)];
        }
        switch ($type) {
            case self::JPEGCODE:
                $this->genJpegCode($fileName);
                break;
            case self::PNGCODE:
                $this->genPngCode($fileName);
                break;
            case self::GIFCODE:
                $this->genGifCode($fileName);
                break;
            case self::MATHCODE:
                $this->genMathCode();
                break;
            default:
                self::$lastError = '未定义类型:'.$type;
                $application->logger->error(self::$lastError);
                return false;
        }
        return true;
    }

}